package com.nc.gateway.filter;

import com.alibaba.fastjson.JSONObject;
import com.plug.result.RetResult;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.*;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 创建人:    xvzhe
 * 创建时间:
 * 修改时间:
 * 版本:      v1.0
 */
@Component
public class AccessFilter implements GlobalFilter, Ordered {
    @Autowired
    DiscoveryClient discoveryClient;
    @Value("${auth.instance}")
    private String instance;


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("token");
        if (!Optional.ofNullable(token).isPresent()) {
            token = exchange.getRequest().getQueryParams().getFirst("token");
        }
        String type = "other";
        if (!Optional.ofNullable(token).isPresent()) {
            type = "web";
            if (!exchange.getRequest().getCookies().isEmpty() && exchange.getRequest().getCookies().containsKey("JSESSIONID")) {
                token = exchange.getRequest().getCookies().get("JSESSIONID").get(0).getValue();
            }
        }
        RestTemplate restTemplate = new RestTemplate();
        List<ServiceInstance> oauthServer = discoveryClient.getInstances(instance);

        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        headers.set("token", token);
        HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
        String path = exchange.getRequest().getPath().toString();
        if (path.indexOf(instance) > 0) {
            String[] p = path.split("/");
            p[1] = "";
            path = "/" + StringUtils.join(p, "/").replace("//", "");
        }
        try {
            if (!path.contains("/login")) {
                ResponseEntity<RetResult> result = restTemplate.exchange("http:" + oauthServer.get(0).getUri().getRawSchemeSpecificPart() + path, Objects.requireNonNull(exchange.getRequest().getMethod()), entity, RetResult.class);
                System.out.println(Objects.requireNonNull(result.getBody()).getCode());
                if (Objects.requireNonNull(result.getBody()).getCode() == 401) {
                    ServerHttpResponse response = exchange.getResponse();
                    JSONObject message = new JSONObject();
                    message.put("status", -1);
                    message.put("data", "鉴权失败");
                    byte[] bits = message.toJSONString().getBytes(StandardCharsets.UTF_8);
                    if (type.equals("web")) {
                        response.setStatusCode(HttpStatus.SEE_OTHER);
                        response.getHeaders().set("Location", "/admin/login");
                        return exchange.getResponse().setComplete();
                    }
                    DataBuffer buffer = response.bufferFactory().wrap(bits);
                    response.setStatusCode(HttpStatus.UNAUTHORIZED);
                    response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
                    return response.writeWith(Mono.just(buffer));
                }
            }
        } catch (Exception e) {

        }
        String finalToken = token;
        ServerHttpRequest host = exchange.getRequest().mutate().headers(httpHeaders -> {
            if (StringUtils.isNotBlank(finalToken)) {
                httpHeaders.add("token", finalToken);
            }
        }).build();
        ServerWebExchange build = exchange.mutate().request(host).build();
        return chain.filter(build);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
